1B11 Programming Exercises 3

Marking Finishes Friday 17th November 2000

It is recommended that you finish by Friday 10th November


Purpose: Interactive programs using keyboard input and arrays.

Goal: Complete as many of these questions as you can. If you are keeping up, you need to do at least the Core questions. The Additional questions are more challenging and are designed to stretch the more confident programmers. Don't worry if you can't do them now, but be prepared to come back and try them later on in the term.

Marking: All questions are binary marked.
To get a question marked, print out the program you have written and a cover sheet from the 1b11 web page. Fill in the cover sheet and attach it to the program listing, then take the work to your lab group demonstrator for marking. The demonstrator may want to see a demonstration of your program running. An answer can be submitted as many times as you like, until it is satisfactory.
All printing should be done on the line printer (a4lp) - don't use up your laser printer quota!

NOTE: You must keep all marked work as it forms a record of your progress. At the end of the course you are required to re-submit all work.


Programming Notes

A number of these exercise questions require input to be read from the keyboard. To simplify this a KeyboardInput class is described in the following notes, which provides input objects that can read data from the keyboard.

The KeyboardInput class

These notes show how to use a class called KeyboardInput for reading values typed in at the keyboard. The class brings together a collection of useful input methods that you can call from your programs. This is the same class that is used in the text book and is listed in the appendices.

Using the class you can write interactive programs that are able to input values of the following types:

The user of your interactive program has to type a value using the correct format for that type. For example, 123 would be a valid int value but abc would not be. Reading input is always tricky as you have to deal with all the strange things that someone may type in!

If something is typed in that cannot be recognised as a value of the type being asked for, a default value is returned, rather than an error being reported. For numbers the default is zero, for char a space and for String an empty string.

Using KeyboardInput

To use the KeyboardInput class save the source code, which is listed below, into a file called KeyboardInput.java (you can use cut and paste from the web page version of these notes). Note the way the KeyboardInput is spelt using a capital K and I. You must use the same combination of upper and lower case letters.

Next compile the code to produce the file KeyboardInput.class. This file, or a copy of it, should then be placed in any directory you are using when working on your exercises. (If you want to be more sophisticated and avoid making copies of the .class file investigate how to use the CLASSPATH environment variable.)

Before any input can be read by a program you need to create a KeyboardInput object using the KeyboardInput class. Do this by having a line in your program that looks like this:

        KeyboardInput in = new KeyboardInput() ;

This line must appear before you do any input and will give you a variable called in that references the KeyboardInput object. Once you have an object you can use it to call input methods. For example, to input an integer you would use:

int x = in.readInteger() ; 

When this statement is executed, the program will wait for you to type in some input. The input must be ended by pressing the <return> key, otherwise nothing more will happen! Once the input has been read an attempt will be made to recognise the characters that were typed as an integer of type int. If successful the int value will be returned. If not, then a default value of 0 is returned. The variable x will be initialised accordingly.

To let someone using your program know that input is expected, it is a good idea to print a message asking for the input. For example:

System.out.print("Type a floating point number: ") ;

double d = in.readDouble() ;

Note the use of print, rather than println, so that the input follows the request on the same line.

The following test program shows the use of all the input methods provided by the class. To run this program, save the source code to a file called KeyboardInputTest.java and compile and run it, having first made sure that a copy of KeyboardInput.class is in the same directory.

class KeyboardInputTest

{

  public static void main(String[] args)

  {

    KeyboardInput in = new KeyboardInput() ;
    System.out.print("Type an integer: ") ;

    int n = in.readInteger() ;

    System.out.println("Integer was: " + n) ;
    System.out.print("Type a long: ") ;

    long l = in.readLong() ;

    System.out.println("Long was: " + l) ;
    System.out.print("Type a double: ") ;

    double d = in.readDouble() ;

    System.out.println("Double was: " + d) ;
    System.out.print("Type a float: ") ;

    float f = in.readFloat() ;

    System.out.println("float was: " + f) ;
    System.out.print("Type a char: ") ;

    char c = in.readCharacter() ;

    System.out.println("char was: " + c) ;
    // Note that reading one character leaves the newline

    // character still in the input buffer. Do an extra

    // read to use it up.

    c = in.readCharacter() ;



    // Newlines are represented using two characters on Microsoft

    // Windows systems, so an further read is needed.

    // c = in.readCharacter() ;
    System.out.print("Type a String: ") ;

    String s = in.readString() ;

    System.out.println("String was: " + s) ;

   }

}

Input Buffering

Input from the keyboard is buffered in an input buffer managed by the operating system. This means that all the characters typed are collected up and temporarily stored until the <return> key is pressed. The operating system keeps your program waiting while you are typing, so your program is not actually doing anything. Only after the <return> key is pressed does your program carry on executing. While your program is waiting we say it is suspended or blocked.

As a result of the buffering your program receives a whole line of characters at a time, not single characters one after another. The line of characters includes a newline character at the end — newline is the character generated by pressing <return>. When you read any type of value, except for char, the newline character is automatically removed and you don't see it. However, when you read a character the newline is left in place and you need to do an extra readCharacter to get rid of it. You can see this being done in the test program above, so don't forget to take this into account when reading characters. If you are using a Microsoft Windows system you will find that newlines are represented by two characters, so an extra read is needed to remove all the characters compared to a Unix system.

Note that due to buffering, calling readCharacter may simply return the next character in the buffer if one is available due to the user having typed in several characters. In this case, there is no need for the program to wait for anything more to be typed in. If programs using readCharacter appear not to wait for input, then check for this situation.

The KeyboardInput class code listing follows. The class uses a number of Java features that we have not covered yet, along with several library classes. At this stage an understanding of how the class works is not needed but it is well worth the challenge of looking through it and trying to work out what all the code does. Use the text book to help. Also, note the way the class has been commented. It has actually been fully commented using documentation comments, which can be automatically processed to produce online documentation in the form of web pages.

import java.io.* ;

/**

 *  A simple input class to read values typed at the command line.  If

 *  an error occurs during input, any exceptions thrown are caught and

 *  a default value returned.

 *

 *  @version 1.1 1999.08.18

 *  @author Graham Roberts

 *  @author Russel Winder

 */

public class KeyboardInput 

{

  /**

   *  The buffered stream that works the keyboard so that we can read

   *  from it sensibly.

   */

  private final BufferedReader in =

    new BufferedReader(new InputStreamReader (System.in)) ;



  /**

   *  Read an <CODE>int</CODE> value from keyboard input.  The default

   *  return value is 0.

   */

  public final synchronized int readInteger() 

  {

    String input = "" ;

    int value = 0 ;

    try 

    {

      input = in.readLine() ;

    }

    catch (IOException e) { }

    if (input != null) 

    {

      try 

      {

        value = Integer.parseInt(input) ;

      }

      catch (NumberFormatException e) { }

    }

    return value ;

  }



  /**

   *  Read a <CODE>long</CODE> value from keyboard input.  The default

   *  return value is 0L.

   */

  public final synchronized long readLong() 

  {

    String input = "" ;

    long value = 0L ;

    try 

    {

      input = in.readLine() ;

    }

    catch (IOException e) { }

    if (input != null) {

      try 

      {

        value = Long.parseLong(input) ;

      }

      catch (NumberFormatException e) { }

    }

    return value ;

  }



  /** 

   * Read a <CODE>double</CODE> value from keyboard input.  The

   *  default return value is 0.0.

   */

  public final synchronized double readDouble() 

  {

    String input = "" ;

    double value = 0.0D ;

    try 

    {

      input = in.readLine() ;

    }

    catch (IOException e) { }

    if (input != null) {

      try 

      {

        value = Double.parseDouble(input) ;

      }

      catch (NumberFormatException e) { }

    }

    return value ;

  }



  /**

   *  Read a <CODE>float</CODE> value from keyboard input.  The

   *  default return value is 0.0F.

   */

  public final synchronized float readFloat() 

  {

    String input = "" ;

    float value = 0.0F ;

    try 

    {

      input = in.readLine() ;

    }

    catch (IOException e) { }

    if (input != null) {

      try 

      {

        value = Float.parseFloat(input) ;

      }

      catch (NumberFormatException e) { }

    }

    return value ;

  }



  /**

   *  Read a <CODE>char</CODE> value from keyboard input.  The default

   *  return value is ' ' (space).

   */

  public final synchronized char readCharacter() 

  {

    char c = ' ' ;

    try 

    {

      c = (char)in.read() ;

    }

    catch (IOException e) {}

    return c ;

  }



  /**

   *  Read an <CODE>String</CODE> value from keyboard input.  The

   *  default return value is "" (the empty string).

   */

  public final synchronized String readString() 

  {

    String s = "";

    try 

    {

      s = in.readLine() ;

    }

    catch (IOException e) {}

    if (s == null) 

    {

      s = "" ;

    }

    return s ;

  }

}

Arrays

The syntax for declaring, creating and using arrays is covered in both the lecture slides and the text book. In summary, an array is created as follows:

int[] myArray = new int[10] ; // An array of 10 ints

An array variable (myArray in the example above), must be explicitly initialised to reference a new array, created with a new expression. A common mistake is to forget to create the array, so always check for this if a program does not compile or work.

Array indexing, the operation used to access array elements, is done using the square bracket notation:

myArray[x] = 10 ;

Don't forget that an array of size 10 is indexed from 0 to 9 — indexing counts from zero. This is easy to get wrong, typically when accessing an array with a loop. A check is made at runtime that the array index given is within the array, so accessing myArray[10] will cause an array bounds error and your program will be terminated. Such errors are common, so check your array indexing and use of loops carefully.

Comparing Strings

Integers and integer variables can be compared using the == operator, for example x == 2. The same operator can be used to compare values of other primitive types. However, strings are objects and trying to compare strings using == won't work in the way expected. In fact, == will compare two string objects to see if they are the same object, not if they represent the same sequence of characters. Due to the complex way in which strings objects are managed this may or may not get you the result you need!

To compare strings properly you need to use the compareTo method:

String s1 = ...

String s2 = ...

int n = s1.compareTo(s2) ;

compareTo will return a value less than zero if s1 comes before s2 alphabetically.
compareTo will return a value less than of zero if s1 is the same as s2.
compareTo will return a value greater than zero if s1 comes after s2 alphabetically.

Strings are compared by looking at each character and using the ordering defined for characters. Does A come before or after a, does 1 come before or after a? The answer is in the text book, or try writing some experimental programs to work out the ordering!

More information about comparing strings can be found in the online documentation under class String.

Accessing characters in a String

A string object holds an array of characters. Each character can be access using the charAt method:

String s1 = "hello" ;



char c = s1.charAt(1) ; // Get the character 'e'

This is like array indexing, except that the square bracket notation is not used. Indexing still counts from 0.

Random Numbers

Random numbers can be generated by an object of class Random (look it up in the Java documentation). The following program illustrates the use of a Random object.

import java.util.Random ; // Don't forget to include this line



class MyRandom 

{ 

  public static void main(String[] args) 

  { 

    Random generator = new Random() ; 

    // Display 10 random integers 

    for (int i = 0 ; i < 10 ; ++i) 

    { 

      System.out.println(generator.nextInt()) ; 

    } 

  } 

}  

Random integers can have any integer value (run the program above and see what it displays).

The line starting with the keyword import tells the Java compiler that class Random is needed by the following program and must be present. A similar line is needed to use the Date or Vector classes, but not for class String.

Colour

Drawing programs can make use of colour! When using a graphics object the method setColor is used to set the drawing colour (note the spelling of colour in setColor — this is correct). The following code will draw a red rectangle:

g.setColor(Color.red) ;

g.drawRect(150,150,50,50) ;

SetColor requires a Color to be given as an argument. The default Colors are:

 Color.black  Color.magenta
 Color.blue  Color.orange
 Color.cyan  Color.pink
 Color.darkGray  Color.red
 Color.gray  Color.white
 Color.green  Color.yellow
 Color.lightGray  

Colours can also be specified using Red, Blue and Green (RGB) values, allowing you to pick any colour you want to work with. For example, to create your own colour you would use:

Color myColor = new Color(10,100,200) ; // Sort of greenish/blue

g.setColor(myColor) ; // Use the color

The three argument values are integers in the range 0-255, representing the mix of red, blue and green values.


Example Questions and Answers

The following are examples of questions and answers, to show how the Java syntax works, and to illustrate the kinds of programs you should be writing. There are further detailed examples in the text book.

Example3.1 Write a program to ask for, and read in using the class KeyboardInput (see the separate notes), your name and a greetings message. Then display both on the screen.

Hint: You need to read in a String values and store then in variables of type String.

Answer:

// Written by A.Person, October 2000

// Answer to Ex3 example question 1

class Q3_1 

{ 

  public static void main(String[] args) 

  { 

    KeyboardInput in = new KeyboardInput() ; 

    System.out.print("Type your name: ") ; 

    String name = in.readString() ; 

    System.out.print("Type in a message: ") ; 

    String message = in.readString() ; 

    System.out.println("\n\nHello, you are: " + name) ; 

    System.out.println("And    your message is: " + message) ; 

  } 

} 

Example3.2 Write a program to read in 10 integers and store them in an array. Then print out the contents of the array.

Answer:

// Written by A.Person, October 2000

// Answer to Ex3 example question 2

class Q3_2

{

  public static void main(String[] args)

  {

    KeyboardInput in = new KeyboardInput() ;

    int[] nums = new int[10] ;

    for (int n = 0 ; n < 10 ; n++)

    {

      int val = 0 ;

      System.out.print("Enter integer " + n +": ") ;

      val = in.readInteger() ;

      nums[n] = val ;

    }

    for (int n = 0 ; n < 10 ; n++)

    {

      System.out.println("Integer " + n + " = " + nums[n]) ;

    }

  }

}


Core questions

Q3.1 Write a program using the KeyboardInput class, that asks for a message (String) and an integer to be input, and then displays the message the number of times denoted by the integer.


Q3.2 Write a program that uses a loop to input a sequence of single characters until the character Q is entered. Remember that type char is used to store characters. Characters can be compared using the == operator.

Note — this is not quite as straightforward as it may seem, as entering a character also results in a newline character being input when the <return> key is pressed. Hence, extra reads are needed to remove the newline character(s). See the KeyboardInputTest program listed in the introductory notes.

What happens if you enter strings into your program, rather than just single characters?


Q3.3 Write a program that inputs a sequence of String values until the word stop is entered.

Hint: You compare strings using compareTo, as outlined in the preceding notes.


Q3.4 Write a program that reads in pairs of strings and determines which string comes alphabetically first.

Hint: compareTo will tell you the ordering.


Q3.5 Write a program to input 10 doubles and store them in an array. Then print out the contents of the array followed by the average of the array elements. Try entering negative as well as positive numbers.


Q3.6 Repeat Q3.5, except that the user should first be asked how many doubles will be entered, rather than the number being fixed at 10.

Hint:: Create an array of the correct size after the user has entered the number of doubles to be input.


Q3.7 Consider a cube composed of an arrangement of smaller cubes. For example, a 3x3x3 cube would look like this (like a Rubik's cube):

How many cubes are on the surface?

Write the simplest possible program you can, that is able to determine the number of cubes on the surface of any n x n x n cube of cubes.

Hint: Thinking hard first will save a lot of time and effort!


Q3.8 Write a program to input 10 words, stored as strings in an array, and then display the words in sorted order.


Q3.9 Write a program to read in 10 lines of text and then print out the number of words contained in those lines.

Hint: Read the earlier notes on accessing characters in a string! You'll also need to define what makes a word as far as your program is concerned.

Another hint: Is it tedious typing in lots of text to test your program? Use emacs to type your text into a file and then use I/O redirection to tell your program to read the file as its input:

prompt> java Q3_8 < myText.txt

The file myText.txt contains your text. The '<' symbol is used to tell the program to read from the file rather than the keyboard.

If you are really paying attention you can use cut and paste to get text into your text file...


Q3.10 Write a program to generate 10000 random integers between 1 and 100. Print out the largest, smallest and the average integers.

How do you make sure all your numbers are between 1 and 100 inclusive?

Do you need an array? Think very carefully about this.


Q3.11 Write a drawing program that generates 1000 random integers between 1 and 10 and draws a bar chart showing how many of each integer occurred. Draw each bar in a different colour.

Hint: Count the integers first then draw the bar chart, making sure that the chart scale is suitable. How do you store the counts? Array...


Q3.12 Write a drawing program to display a pattern of blue and yellow crosses, like this:

Hint: Find the pattern by which the colours alternate row by row.
An array of colours forming the pattern might be helpful...


Additional questions


3.14 Write a program to display the current date and time


3.15 Repeat Q3.6 but use ArrayList object rather than an array.

Hint: See class ArrayList in the Java documentation. You will not be able to use square bracket syntax ([]) with an arraylist but it can store as many values as you like without having to specify a fixed size. More importantly, you cannot store double values in a vector. Use class Double objects instead.


3.16 Write a drawing program to display a Rubik's cube from any desired position.